package org.scache.log;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 内部Logger
 *
 * @author junfeng
 * @since 15/7/6 16:38
 */
public class InternalLogger {
    private final static ExecutorService executorService = Executors.newFixedThreadPool(1);
    private final static Logger LOGGER = LoggerFactory.getLogger(InternalLogger.class);
    private final static boolean debugEnabled;
    private final static boolean infoEnabled;
    private final static boolean warnEnabled;
    private final static boolean errorEnabled;

    static {
        debugEnabled = LOGGER.isDebugEnabled();
        infoEnabled = LOGGER.isInfoEnabled();
        warnEnabled = LOGGER.isWarnEnabled();
        errorEnabled = LOGGER.isErrorEnabled();
        System.out.println("scache-log-switch:" + debugEnabled + "," + infoEnabled + "," + warnEnabled + "," + errorEnabled);
    }

    static boolean isAsyncLog = true;

    static InternalLogger singleton = new InternalLogger();

    public static InternalLogger logger() {
        return singleton;
    }

    /**
     * 日志信息
     *
     * @author wangyajun
     * @since 2015-3-27 上午9:57:13
     */
    static abstract class LogInfo implements Runnable {
        final long logTime = System.currentTimeMillis();
        final Object message;
        final Throwable e;

        LogInfo(Object message, Throwable e) {
            this.message = message;
            this.e = e;
        }
    }

    public static void debug(Object message) {
        debug(message, null);
    }

    public static void debug(final Object message, final Throwable e) {
        if (isDebugenabled()) {
            if (isAsyncLog) {
                executorService.execute(new LogInfo(message, e) {

                    @Override
                    public void run() {
                        doDebug("[" + logTime + "]" + message, e);
                    }
                });
            } else {
                doDebug(message, e);
            }
        }
    }

    static void doDebug(Object message, Throwable e) {
        if (e != null) {
            LOGGER.debug(String.valueOf(message), e);
        } else {
            LOGGER.debug(String.valueOf(message));
        }
    }

    public static void info(Object message) {
        info(message, null);
    }

    public static void info(final Object message, final Throwable e) {
        if (isInfoenabled()) {
            if (isAsyncLog) {
                executorService.execute(new LogInfo(message, e) {

                    @Override
                    public void run() {
                        doInfo("[" + logTime + "]" + message, e);
                    }
                });
            } else {
                doInfo(message, e);
            }
        }
    }

    static void doInfo(Object message, Throwable e) {
        if (e != null) {
            LOGGER.info(String.valueOf(message), e);
        } else {
            LOGGER.info(String.valueOf(message));
        }
    }

    public static void warn(Object message) {
        warn(message, null);
    }

    public static void warn(final Object message, final Throwable e) {
        if (isWarnenabled()) {
            if (isAsyncLog) {
                executorService.execute(new LogInfo(message, e) {

                    @Override
                    public void run() {
                        doWarn("[" + logTime + "]" + message, e);
                    }
                });
            } else {
                doWarn(message, e);
            }
        }
    }

    static void doWarn(Object message, Throwable e) {
        if (e != null) {
            LOGGER.warn(String.valueOf(message), e);
        } else {
            LOGGER.warn(String.valueOf(message));
        }
    }

    public static void error(Object message) {
        error(message, null);
    }

    public static void error(final Object message, final Throwable e) {
        if (isErrorenabled()) {
            if (isAsyncLog) {
                executorService.execute(new LogInfo(message, e) {

                    @Override
                    public void run() {
                        doError("[" + logTime + "]" + message, e);
                    }
                });
            } else {
                doError(message, e);
            }
        }
    }

    static void doError(Object message, Throwable e) {
        if (e != null) {
            LOGGER.error(String.valueOf(message), e);
        } else {
            LOGGER.error(String.valueOf(message));
        }
    }

    /**
     * @return the debugenabled
     */
    public static boolean isDebugenabled() {
        return debugEnabled;
    }

    /**
     * @return the infoenabled
     */
    public static boolean isInfoenabled() {
        return infoEnabled;
    }

    /**
     * @return the warnenabled
     */
    public static boolean isWarnenabled() {
        return warnEnabled;
    }

    /**
     * @return the errorenabled
     */
    public static boolean isErrorenabled() {
        return errorEnabled;
    }


    private InternalLogger() {
    }
}
